package com.aluka.nirvana.framework.core.model;

import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.Part;
import java.io.*;

/**
 * 自定义媒体文件
 * @author gongli
 * @since 2020/5/8
 */  
public class NirvanaMultipartFile implements MultipartFile {

    @Setter
    private String contentType;
    private String originalFilename;
    private String name;
    private byte[] fileBytes;

    /**
     *
     * @param name 表单参数名
     * @param originalFilename 文件名
     * @param fileBytes 文件字节数组
     */
    public NirvanaMultipartFile (String name,String originalFilename, byte[] fileBytes){
        this.name = name;
        this.originalFilename = originalFilename;
        this.fileBytes = fileBytes;
    }

    /**
     * Return the name of the parameter in the multipart form.
     *
     * @return the name of the parameter (never {@code null} or empty)
     */
    @Override
    public String getName() {
        return this.name;
    }

    /**
     * Return the original filename in the client's filesystem.
     * <p>This may contain path information depending on the browser used,
     * but it typically will not with any other than Opera.
     *
     * @return the original filename, or the empty String if no file has been chosen
     * in the multipart form, or {@code null} if not defined or not available
     * @see CommonsMultipartFile#setPreserveFilename
     */
    @Override
    public String getOriginalFilename() {
        return this.originalFilename;
    }

    /**
     * Return the content type of the file.
     *
     * @return the content type, or {@code null} if not defined
     * (or no file has been chosen in the multipart form)
     */
    @Override
    public String getContentType() {
        return this.contentType;
    }

    /**
     * Return whether the uploaded file is empty, that is, either no file has
     * been chosen in the multipart form or the chosen file has no content.
     */
    @Override
    public boolean isEmpty() {
        return fileBytes == null || fileBytes.length == 0;
    }

    /**
     * Return the size of the file in bytes.
     *
     * @return the size of the file, or 0 if empty
     */
    @Override
    public long getSize() {
        return fileBytes == null ? 0 : fileBytes.length;
    }

    /**
     * Return the contents of the file as an array of bytes.
     *
     * @return the contents of the file as bytes, or an empty byte array if empty
     * @throws IOException in case of access errors (if the temporary store fails)
     */
    @Override
    public byte[] getBytes() throws IOException {
        return this.fileBytes;
    }

    /**
     * Return an InputStream to read the contents of the file from.
     * <p>The user is responsible for closing the returned stream.
     *
     * @return the contents of the file as stream, or an empty stream if empty
     * @throws IOException in case of access errors (if the temporary store fails)
     */
    @Override
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(fileBytes);
    }

    /**
     * Transfer the received file to the given destination file.
     * <p>This may either move the file in the filesystem, copy the file in the
     * filesystem, or save memory-held contents to the destination file. If the
     * destination file already exists, it will be deleted first.
     * <p>If the target file has been moved in the filesystem, this operation
     * cannot be invoked again afterwards. Therefore, call this method just once
     * in order to work with any storage mechanism.
     * <p><b>NOTE:</b> Depending on the underlying provider, temporary storage
     * may be container-dependent, including the base directory for relative
     * destinations specified here (e.g. with Servlet 3.0 multipart handling).
     * For absolute destinations, the target file may get renamed/moved from its
     * temporary location or newly copied, even if a temporary copy already exists.
     *
     * @param dest the destination file (typically absolute)
     * @throws IOException           in case of reading or writing errors
     * @throws IllegalStateException if the file has already been moved
     *                               in the filesystem and is not available anymore for another transfer
     * @see Part#write(String)
     */
    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
        new FileOutputStream(dest).write(fileBytes);
    }
}
